using System;
using Tarkin.InfrastructureLibrary.Core.Basic;
using Tarkin.InfrastructureLibrary.Core.PrimitiveTypes;
using Tarkin.InfrastructureLibrary.Tests.Core.Basic.TestUtilities.ConcreteClasses;
using NUnit.Framework;

namespace Tarkin.InfrastructureLibrary.Tests.Core.Basic
{
    /// <summary>
    /// ParameterTests is the NUnit TestFixture for the Tarkin.InfrastructureLibrary.Core.Basic.Parameter class.
    /// </summary>
    [TestFixture]
    public class ParameterTests
    {
        [Test]
        public void TestOverloadedConstructorOneParameter ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            Parameter parameter = new Parameter ( typedElement );

            Assert.IsNotNull ( parameter );
            Assert.AreEqual ( "Typed Element name", parameter.Name );
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestOverloadedConstructorOneParameterNullParameter ()
        {
            Parameter parameter = new Parameter ( null );
        }

        [Test]
        public void TestOverloadedConstructorTwoParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ();
            Parameter parameter = new Parameter ( typedElement, multiplicityElement );

            Assert.IsNotNull ( parameter );
            Assert.AreEqual ( "Typed Element name", parameter.Name );
        }

        [Test]
        public void TestOverloadedConstructorThreeParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ();
            Operation operation = new Operation ( typedElement );
            Parameter parameter = new Parameter ( typedElement, multiplicityElement, operation );

            Assert.IsNotNull ( parameter );
            Assert.AreEqual ( "Typed Element name", parameter.Name );
            Assert.AreEqual ( "Typed Element name", operation.Name );
        }

        [Test]
        public void TestOverloadedConstructorFiveParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ();
            UnlimitedNatural unlimitedNatural = new UnlimitedNatural ( UnlimitedNatural.UnlimitedNaturalInfinity );
            Parameter parameter = new Parameter ( typedElement, true, false, 27, unlimitedNatural );

            Assert.IsNotNull ( parameter );
            Assert.AreEqual ( true, parameter.IsOrdered );
            Assert.AreEqual ( false, parameter.IsUnique );
            Assert.AreEqual ( 27, parameter.Lower );
            Assert.AreEqual ( UnlimitedNatural.UnlimitedNaturalInfinity, parameter.Upper.Value );
        }

        [Test]
        public void TestOverloadedConstructorSixParameters ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ();
            UnlimitedNatural unlimitedNatural = new UnlimitedNatural ( UnlimitedNatural.UnlimitedNaturalInfinity );
            Operation operation = new Operation ( typedElement );
            Parameter parameter = new Parameter ( typedElement, true, false, 27, unlimitedNatural, operation );

            Assert.IsNotNull ( parameter );
            Assert.AreEqual ( true, parameter.IsOrdered );
            Assert.AreEqual ( false, parameter.IsUnique );
            Assert.AreEqual ( 27, parameter.Lower );
            Assert.AreEqual ( UnlimitedNatural.UnlimitedNaturalInfinity, parameter.Upper.Value );
            Assert.AreEqual ( "Typed Element name", operation.Name );
        }

        [Test]
        public void TestTypeProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            ConcreteType type = new ConcreteType ( "Type name" );
            Parameter parameter = new Parameter ( typedElement );

            parameter.Type = type;

            Assert.IsNotNull ( parameter.Type );
            Assert.AreEqual ( "Type name", parameter.Type.Name );
        }

        [Test]
        public void TestNameProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            Parameter parameter = new Parameter ( typedElement );

            parameter.Name = "Test";
            
            Assert.AreEqual ( "Test", parameter.Name );
        }

        [Test]
        public void TestOperationProperty ()
        {
            ConcreteTypedElement typedElement = new ConcreteTypedElement ( "Typed Element name" );
            ConcreteMultiplicityElement multiplicityElement = new ConcreteMultiplicityElement ();
            Operation operation = new Operation ( typedElement );
            Parameter parameter = new Parameter ( typedElement, multiplicityElement, operation );

            Assert.IsNotNull ( parameter.Operation );
            Assert.AreEqual ( "Typed Element name", parameter.Operation.Name );
        }
    }
}
